﻿using Futajma.MigrationStudio.DataDefinition;
using Futajma.MigrationStudio.SharePointPersistance;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;

namespace LLTreeManagementApplication.Dialog
{
    public partial class RedirectorExport : Form
    {
        TreeNode _node;
        Dictionary<DataNode, string> _linkList = new Dictionary<DataNode, string>();
        Dictionary<string, XElement> _loadedExport = new Dictionary<string, XElement>();
        List<string> _logList = new List<string>();
        //int _errorCounter = 0;
        XElement _elInfo = new XElement("Info");
        XElement _elItems = new XElement("Items");
        string _filename = string.Empty;
        string _loadedReportFileName = string.Empty;


        private readonly BackgroundWorker _worker;


        public RedirectorExport(TreeNode node)
        {
            _node = node;
            InitializeComponent();
#if DEBUG
            btnTest.Visible = true;
            txtTestUrl.Visible = true;
#endif

            txtLandingPageUrl.Text = ConfigurationManager.AppSettings["LandingPageURL"];

            _worker = new BackgroundWorker();
            _worker.WorkerSupportsCancellation = true;
            _worker.WorkerReportsProgress = true;
            _worker.DoWork += ProcessWork;
            _worker.ProgressChanged += worker_ProgressChanged;
            _worker.RunWorkerCompleted += worker_RunWorkerCompleted;

        }

        private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

            foreach (var item in _loadedExport.Values)
            {
                _elItems.Add(item);
            }

            SaveList(_filename);

            lbxLog.BeginUpdate();
            lbxLog.Items.Clear();

            foreach (var line in _logList)
            {
                lbxLog.Items.Add(line);
            }

            lbxLog.EndUpdate();

            using (var sw = new StreamWriter(Path.ChangeExtension(_filename, ".txt"), false, Encoding.Unicode))
            {
                foreach (var item in lbxLog.Items)
                {
                    sw.Write(item.ToString() + Environment.NewLine);
                }
            }

            _loadedReportFileName = string.Empty;

            btnCancel.Enabled = false;
            btnExport.Enabled = true;

            btnClearLog.Enabled = true;
            bntExportLog.Enabled = true;

            btnLoadExport.Enabled = true;
            btnClearLog.Enabled = true;
            bntExportLog.Enabled = true;
            cbxExcludeSubSites.Enabled = false;
            grbParameters.Enabled = false;
            rbLinkToDocument.Enabled = false;
            rbRedirectoToId.Enabled = false;
            rbLinkToUrl.Enabled = false;
            btnSaveExportAs.Enabled = true;

        }

        private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            prgExport.Value = e.ProgressPercentage;
            var item = e.UserState as string;
            lbxLog.Items.Add(item);
        }

        private void ProcessWork(object sender, DoWorkEventArgs e)
        {
            int count = 0;
            XElement items = e.Argument as XElement;

            foreach (var key in _linkList.Keys)
            {
                if (_worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    return;
                }

                var targetUrl = _linkList[key];
                count++;
                _logList.Add(string.Format("Process [{0}] at {1}", targetUrl, DateTime.Now));
                var info = string.Format("Process {0} of {1} : [{2}] at {3}", count, _linkList.Count, targetUrl, DateTime.Now);
                int percentComplete = (int)((float)count / (float)_linkList.Count * 100);

                _worker.ReportProgress(percentComplete, info);
                try
                {
                    targetUrl = GetTargetUrl(targetUrl);
                    XElement item = new XElement("I");
                    item.Add(new XAttribute("sU", System.Web.HttpUtility.UrlDecode(key.SourceUrl)));
                    item.Add(new XAttribute("tU", targetUrl));
                    item.Add(new XAttribute("sId", key.SourceId));
                    items.Add(item);
                    _logList.Add(string.Format("Linked to  [{0}]", targetUrl));
                }
                catch (Exception ex)
                {
                    _logList.Add(string.Format("Error [{0}][{1}]", ex.Message, ex.InnerException));
                    _worker.ReportProgress(percentComplete, string.Format("Error [{0}][{1}]", ex.Message, ex.InnerException));
                }
            }
            _logList.Add(string.Format("Start done at {0}", DateTime.Now));
        }

        private void rbLinkToDocument_CheckedChanged(object sender, EventArgs e)
        {
            SetParameterDialogStatus();
        }

        private void SetParameterDialogStatus()
        {
            grbParameters.Enabled = rbLinkToUrl.Checked;
        }

        private void rbLinkToUrl_CheckedChanged(object sender, EventArgs e)
        {
            SetParameterDialogStatus();
        }

        private void SaveList(string filename)
        {
            //SaveFileDialog saveDlg = new SaveFileDialog();
            //saveDlg.RestoreDirectory = true;
            //saveDlg.Filter = "xml File|*.xml";
            //saveDlg.Title = "Select a exporter xml file";

            //if (saveDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            //{
            _elInfo.Save(filename);
            //}
        }

        private void btnExport_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveDlg = new SaveFileDialog();
            saveDlg.RestoreDirectory = true;
            saveDlg.Filter = "xml File|*.xml";
            saveDlg.Title = "Select a exporter xml file";

            if (saveDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                _filename = saveDlg.FileName;

                btnClearLog.Enabled = false;
                bntExportLog.Enabled = false;

                prgExport.Value = 0;
                _logList.Clear();
                //lbxLog.Items.Clear();

                _linkList.Clear();

                LoadExportedList();

                foreach (TreeNode node in _node.Nodes)
                {
                    ProcessTreeNode(node, false);
                }

                prgExport.Maximum = 100;
                _logList.Add(string.Format("Start export at {0}", DateTime.Now));

                CreateList();

            }
        }

        private void LoadExportedList()
        {
            _loadedExport.Clear();
            if (!string.IsNullOrEmpty(_loadedReportFileName))
            {
                var doc = XDocument.Load(_loadedReportFileName);

                var iList = doc.Descendants("I");

                foreach(var item in iList)
                {
                    var su = (string)item.Attribute("sU");

                    if (!_loadedExport.ContainsKey(su))
                    {
                        _loadedExport.Add(su, item);
                    }
                    else
                    {
                        _logList.Add(string.Format("SourceUrl in loaded export already exists: {0}", su));
                    }
                }
            }
        }


        private string GeneratePath(TreeNode node, bool flattenStructure)
        {
            var data = node.Tag as DataNode;

            if (node.Parent != null)
            {
                if (flattenStructure)
                {
                    if (data.SharePointType == SharePointType.Folder)
                    {
                        return GeneratePath(node.Parent, flattenStructure);
                    }
                }

                if (data.SharePointType == SharePointType.SiteCollection)
                {
                    return data.TargetPath;
                    //return string.Format("{0}/{1}", data.TargetPath, node.Text);
                }
                else if (data.SharePointType == SharePointType.Site && !string.IsNullOrEmpty(data.TargetPath))
                {
                    return string.Format("{0}/{1}", GeneratePath(node.Parent, flattenStructure), data.TargetPath);
                }
                else if (data.SharePointType == SharePointType.DocLibrary && !string.IsNullOrEmpty(data.TargetPath))
                {
                    return string.Format("{0}/{1}", GeneratePath(node.Parent, flattenStructure), data.TargetPath);
                }
                else
                {
                    return string.Format("{0}/{1}", GeneratePath(node.Parent, flattenStructure), data.Title);
                }
            }
            else
            {
                if (data.SharePointType != SharePointType.Application)
                {
                    return node.Text;
                }
                else
                {
                    return string.Empty;
                }
            }
        }

        private void ProcessTreeNode(TreeNode node, bool flattenStructure)
        {
            var data = node.Tag as DataNode;

            if (data.SharePointType == SharePointType.Site && cbxExcludeSubSites.Checked)
            {
                return;
            }

            if (data.SharePointType == SharePointType.DocLibrary)
            {
                flattenStructure = data.RemoveFolderStructure;
            }

            if (data.SharePointType == SharePointType.Item || data.SharePointType == SharePointType.Document)
            {
                var targetPath = GeneratePath(node, flattenStructure);
                //var sourceId = string.IsNullOrEmpty(data.SourceId) ? targetPath : data.SourceId;

                if (!string.IsNullOrEmpty(data.SourceUrl) && !_loadedExport.ContainsKey(data.SourceUrl))
                {
                    _linkList.Add(data, targetPath);
                }
            }
            foreach (TreeNode child in node.Nodes)
            {
                ProcessTreeNode(child, flattenStructure);
            }
        }

        public void CreateList()
        {

            _elInfo = new XElement("Info");
            _elItems = new XElement("Items");
            _elInfo.Add(_elItems);

            //_logList.Clear();

            _worker.RunWorkerAsync(_elItems);
            btnExport.Enabled = false;
            btnCancel.Enabled = true;
            btnClearLog.Enabled = false;
            bntExportLog.Enabled = false;
            btnLoadExport.Enabled = false;

            cbxExcludeSubSites.Enabled = false;
            grbParameters.Enabled = false;
            rbLinkToDocument.Enabled = false;
            rbRedirectoToId.Enabled = false;
            rbLinkToUrl.Enabled = false;
            btnSaveExportAs.Enabled = false;
        }


        //    foreach (var key in _linkList.Keys)
        //    {
        //        prgExport.Value++;
        //        var targetUrl = _linkList[key];

        //        lbxLog.Items.Add(string.Format("Process [{0}] at {1}", targetUrl,  DateTime.Now));

        //        try
        //        {
        //            targetUrl = GetTargetUrl(targetUrl);
        //            XElement item = new XElement("I");
        //            item.Add(new XAttribute("sU", System.Web.HttpUtility.UrlDecode(key.SourceUrl)));
        //            item.Add(new XAttribute("tU", targetUrl));
        //            item.Add(new XAttribute("sId", key.SourceId));
        //            docs.Add(item);
        //            lbxLog.Items.Add(string.Format("Linked to  [{0}]", targetUrl));
        //            Application.DoEvents();
        //        }
        //        catch (Exception ex)
        //        {
        //            lbxLog.Items.Add(string.Format("Error [{0}][{1}]", ex.Message, ex.InnerException));
        //        }
        //    }
        //    el.Save(fileName);
        //    MessageBox.Show(string.Format("Export done!", "Information");
        //}

        private string GetTargetUrl(string targetUrl)
        {
            string url = targetUrl;

            if (rbRedirectoToId.Checked == true)
            {
                url = SharePoint2010Persistence.GetFilePropertyPath(targetUrl);
            }

            if (rbLinkToUrl.Checked == true)
            {
                if (rbNoParameter.Checked == true)
                {
                    url = txtLandingPageUrl.Text;
                }
                if (rbFilenameAsParameter.Checked == true)
                {
                    url = string.Format("{0}{1}", txtLandingPageUrl.Text, targetUrl);
                }
                if (rbIDASParameter.Checked == true)
                {
                    url = string.Format("{0}{1}", txtLandingPageUrl.Text, System.Web.HttpUtility.UrlEncode(SharePoint2010Persistence.GetFilePropertyPath(targetUrl)));

                }
            }

            //url = System.Web.HttpUtility.HtmlDecode(url);
            return url;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            var file = SharePoint2010Persistence.GetFilePropertyPath(txtTestUrl.Text);

            MessageBox.Show(file);

            MessageBox.Show(System.Web.HttpUtility.UrlDecode(file));

            MessageBox.Show(System.Web.HttpUtility.UrlEncode(file));

            //file = SharePoint2010Persistence.GetFilePropertyPath("http://win-qdqqqejjk0o/Documents/test.txt");
            //file = SharePoint2010Persistence.GetFilePropertyPath("http://win-qdqqqejjk0o/sub1/Documents/folder1/folder2/test.txt");
            //file = SharePoint2010Persistence.GetFilePropertyPath("http://win-qdqqqejjk0o/sub1/sub11/Documents/folder11/test.txt");

        }

        private void btnClearLog_Click(object sender, EventArgs e)
        {
            lbxLog.Items.Clear();
        }

        private void bntExportLog_Click(object sender, EventArgs e)
        {
            var saveFile = new SaveFileDialog();
            saveFile.Filter = "Text (*.txt)|*.txt";
            if (saveFile.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                using (var sw = new StreamWriter(saveFile.FileName, false))
                {
                    foreach (var item in lbxLog.Items)
                    {
                        sw.Write(item.ToString() + Environment.NewLine);
                    }
                }
                MessageBox.Show("Log file saved", "Information");
            }
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            _worker.CancelAsync();
        }

        private void btnSaveExportAs_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveDlg = new SaveFileDialog();
            saveDlg.RestoreDirectory = true;
            saveDlg.Filter = "xml File|*.xml";
            saveDlg.Title = "Select a exporter xml file";

            if (saveDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                SaveList(saveDlg.FileName);
            }
        
        }

        private void btnLoadExport_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.RestoreDirectory = true;
            dlg.Filter = "xml File|*.xml";
            dlg.Title = "Select a exporter xml file";

            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                _loadedReportFileName = dlg.FileName;
            }
        }

        private void btnTest_Click(object sender, EventArgs e)
        {
            var file = SharePoint2010Persistence.GetFilePropertyPath(txtTestUrl.Text);

            MessageBox.Show(file);
        }
    }
}
